package net.csdn.business.common.utils;

import cn.hutool.core.io.IoUtil;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import cn.hutool.extra.pinyin.PinyinUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import net.csdn.business.common.constant.CommonConstants;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @author wanghang
 * @version 1.0
 * @date 2022/6/29 14:44
 */
public class CommonUtil {

    public final static String DF_DATETIME = "yyyy-MM-dd HH:mm:ss";

    public final static String Y_M_D = "yyyy-MM-dd";

    public final static String ZN_Y_M_D = "yyyy年MM月dd日";

    public final static String Y_M_D_SPOT = "yyyy.MM.dd";

    public final static String DF_DATETIME_XXX = "yyyy-MM-dd'T'HH:mm:ssXXX";

    public final static String DF_DATETIME_UTC = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

    public final static DateTimeFormatter Y_M_D_H_M_S_Z = DateTimeFormatter.ofPattern(DF_DATETIME_UTC);

    public final static String MD5_SLAT = "ATOM_GIT_MD5_SLAT@";

    /**
     * 获取当前时分秒
     *
     * @return
     */
    public static String getCrrDateTimeStr() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(DF_DATETIME));
    }


    public static Date formatUtcDateTime(String dateTime, DateTimeFormatter dateTimeFormat) {
        try {
            return Date.from(LocalDateTime.parse(dateTime, dateTimeFormat).plusHours(8L).atZone(ZoneId.systemDefault()).toInstant());
        } catch (Exception ignored) {
        }
        return new Date();
    }

    public static Date formatUtcDateTime(String dateTime) {
        return formatUtcDateTime(dateTime, Y_M_D_H_M_S_Z);
    }

    public static String formatStringDate(String date, String inputFormat, String format) {
        if (StringUtils.isBlank(date)) {
            return null;
        }
        return LocalDateTime.parse(date, DateTimeFormatter.ofPattern(inputFormat)).atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern(format));
    }

    public static String date2String(Date date, String df) {
        try {
            return new SimpleDateFormat(df).format(date);
        } catch (Exception e) {
            return CommonConstants.BLACK;
        }
    }

    /**
     * 获取MD5
     *
     * @param str
     * @return
     */
    public static String getMd5(String str) {
        if (StringUtils.isBlank(str)) {
            return CommonConstants.BLACK;
        }
        try {
            str = MD5_SLAT + str;
            MessageDigest md = MessageDigest.getInstance(CommonConstants.MD5);
            md.update(str.getBytes(CommonConstants.UTF8));
            byte bytes[] = md.digest();
            StringBuilder result = new StringBuilder();
            for (int i = 0; i < bytes.length; i++) {
                result.append(Integer.toHexString((0x000000FF & bytes[i]) | 0xFFFFFF00).substring(6));
            }
            return result.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return str;
        }
    }

    /**
     * 校验namespace合法性
     *
     * @param namespace
     * @return
     */
    public static boolean checkNamespace(String namespace) {
        return Pattern.matches(CommonConstants.NAME_SPACE_REGEX, namespace);
    }

    /**
     * 手机号脱敏
     *
     * @param mobile
     * @return
     */
    public static String mobileEncrypt(String mobile) {
        if (StringUtils.isEmpty(mobile) || (mobile.length() != 11)) {
            return mobile;
        }
        try {
            return mobile.replaceAll("(\\w{3})\\w*(\\w{4})", "$1****$2");
        } catch (Exception e) {
            e.printStackTrace();
            return mobile;
        }
    }

    /**
     * utc时间格式转yyyy-MM-dd HH:mm:ss
     *
     * @param isAdd8Hour 是否加8小时
     * @param dateStr
     * @return
     */
    public static String formatUtcDate2Str(boolean isAdd8Hour, String dateStr) {
        try {
            DateTimeFormatter pattern = DateTimeFormatter.ofPattern(DF_DATETIME_XXX);
            LocalDateTime localDateTime = LocalDateTime.parse(dateStr, pattern);
            return localDateTime.format(DateTimeFormatter.ofPattern(DF_DATETIME));
        } catch (Exception e) {
            return getUtcPlusStr(isAdd8Hour, dateStr);
        }
    }

    /**
     * utc时间格式转yyyy-MM-dd HH:mm:ss
     *
     * @param isAdd8Hour 是否加8小时
     * @param dateStr
     * @return
     */
    public static String getUtcPlusStr(boolean isAdd8Hour, String dateStr) {
        try {
            DateTimeFormatter pattern = DateTimeFormatter.ofPattern(DF_DATETIME_UTC);
            LocalDateTime localDateTime = LocalDateTime.parse(dateStr, pattern).plusHours(CommonConstants.INT_EIGHT);
            if (isAdd8Hour) {
                localDateTime = localDateTime.plusHours(CommonConstants.INT_EIGHT);
            }
            return localDateTime.format(DateTimeFormatter.ofPattern(DF_DATETIME));
        } catch (Exception e) {
            return dateStr;
        }
    }

    public static String getPinyinStr(String str) {
        try {
            return PinyinUtil.getPinyin(str, CommonConstants.BLACK);
        } catch (Exception e) {
            return str;
        }
    }

    public static String urlEncode(String str) {
        try {
            return URLEncoder.encode(str, CommonConstants.UTF_8);
        } catch (Exception e) {
            return str;
        }
    }

    /**
     * 导出数据到excel文件
     *
     * @param fileName  导出文件名
     * @param headerMap 表头字段映射
     * @param rows      行数据
     * @param response
     * @throws IOException
     */
    public static void exportExcel(String fileName,
                                   Map<String, String> headerMap,
                                   List<Map<String, Object>> rows,
                                   HttpServletResponse response) throws IOException {
        // 导出excel
        ExcelWriter writer = ExcelUtil.getWriter();
        // 设置Header
        writer.setHeaderAlias(headerMap);
        // 设置默认宽高
        writer.setDefaultRowHeight(CommonConstants.INT_TWENTY);
        for (int i = CommonConstants.INT_ZERO; i < headerMap.size(); i++) {
            writer.setColumnWidth(i, CommonConstants.INT_THIRTY);
        }
        writer.write(rows, true);
        response.setContentType(CommonConstants.CONTENT_TYPE_EXCEL);
        response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(fileName, CommonConstants.UTF_8));
        ServletOutputStream out = response.getOutputStream();
        writer.flush(out, true);
        writer.close();
        IoUtil.close(out);
    }

    public static String getProjectRootNs(String pathWithNamespace) {
        if (StringUtils.isBlank(pathWithNamespace)) {
            return CommonConstants.BLACK;
        }
        return pathWithNamespace.substring(CommonConstants.INT_ZERO, pathWithNamespace.lastIndexOf(CommonConstants.SLASH));
    }

    public static String genSign(String s) {
        Digester md5 = new Digester(DigestAlgorithm.MD5);
        return md5.digestHex(s);
    }

    public static boolean verifySign(String s, String signed) {
        if (StringUtils.isBlank(signed) || StringUtils.isBlank(s)) {
            return false;
        }
        return signed.equals(genSign(s));
    }

}